﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Web.Http;
using CompanySearch.Library.Mongo;
using MongoEntities = CompanySearch.Library.Mongo;
using DTOEntities = CompanySearch.Library.DTOs;
using CompanySearch.Library.Repository;


namespace Sustainalytics.Services.Admin.WebApi.Controllers
{
    public class CompanyController : ApiController
    {
        private static MongoRepository mongoRepository;
        private static IRepository esRepository;


        public CompanyController()
        {
            string connectionString = "mongodb://localhost:27017/DSRRaw";
            //string connectionString = "mongodb://ec2-54-74-145-144.eu-west-1.compute.amazonaws.com:27017/DSRRaw";

            //todo: use lazy //thread safe
            mongoRepository = mongoRepository ?? new MongoRepository(connectionString);

            //todo: use lazy -> thread safe
            esRepository = esRepository ?? new CompanySearch.Library.EleasticSearch.ESRepository("http://localhost:9200/");
        }


        [HttpPost]
        [Route("api/company/search")]
        public DTOEntities.CompanySearchResult Search(DTOEntities.CompanySearchData data)
        {
            return this.DoSearch(data, mongoRepository);
        }


        [HttpPost]
        [Route("api/company/essearch")]
        public DTOEntities.CompanySearchResult EsSearch(DTOEntities.CompanySearchData data)
        {
            return this.DoSearch(data, esRepository);
        }


        private DTOEntities.CompanySearchResult DoSearch(DTOEntities.CompanySearchData data, IRepository repository)
        {
            int pageSize = 20;

            if (data == null || string.IsNullOrEmpty(data.Query))
                return new DTOEntities.CompanySearchResult();

            var textToMatch = data.Query.ToLowerInvariant();

            var companies = new List<DTOEntities.Company>();

            if (data.Position == null || (data.Position.ContainsIndex == 0 && data.Position.StartsWithIndex == 0))
            {
                var ids = repository.GetCompaniesByAttribute(textToMatch);
                pageSize = Math.Max(pageSize - ids.Count, 0);

                companies.AddRange(ToCompanyDtos(repository.GetCompaniesByIds(ids), 20));
            }
          
            int containsIndex = 0;
            int startsWithIndex = 0;

            if (data.Position != null)
            {
                containsIndex = data.Position.ContainsIndex;
                startsWithIndex = data.Position.StartsWithIndex;
            }

            if (startsWithIndex >= 0)
            {
                var startsWithResults = repository.GetCompanyByStartsWith(textToMatch, startsWithIndex, pageSize + 1);
                startsWithIndex = startsWithIndex + Math.Min(startsWithResults.Count, pageSize);
                if (startsWithResults.Count <= pageSize)
                {
                    startsWithIndex = -1;
                }

                var dtos = ToCompanyDtos(startsWithResults, pageSize);

                companies.AddRange(dtos);
               
            }

            if (containsIndex >= 0 && companies.Count < pageSize)
            {
                var take = pageSize - companies.Count;
                var containsResults = repository.GetCompanyByContains(textToMatch, containsIndex, take + 1);
                containsIndex = containsIndex + Math.Min(containsResults.Count, take);
                if (containsResults.Count <= take)
                {
                    containsIndex = -1;
                }
                var dtos = ToCompanyDtos(containsResults, take);
                companies.AddRange(dtos);
            }

            var position = new DTOEntities.SearchIndex { ContainsIndex = containsIndex, StartsWithIndex = startsWithIndex };
         
            return new DTOEntities.CompanySearchResult { Companies = companies, Position = position };
        }




        private static IEnumerable<DTOEntities.Company> ToCompanyDtos(List<Company> startsWithResults, int maxItems)
        {
            var dtos = (from c in startsWithResults
                       select new DTOEntities.Company { Name = c.Name, Ticker = null }).Take(maxItems);
            return dtos;
        }

        
    }
}
